package com.commons.dbutils.nio;

import java.net.*;

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;

import com.qunar.sandglass.util.HttpClientUtils;

/**
 * 
 * 模拟http请求类 非线程安全类
 */
public class Http {
	private static final Logger logger = Logger.getLogger(Http.class.getName());
	protected SocketChannel client;
	protected byte[] receiver = null;
	protected URL target;
	private String content;

	Map<String, String> header = new HashMap<String, String>();

	public Http() {
	}

	public Http(String url) {
		get(url);
	}

	/* GET方法根据URL，会请求文件、数据库查询结果、程序运行结果等多种内容 */
	public void get(String url) {
		try {
			checkHTTP(url);
			openServer(target.getHost(), target.getPort());

			sendMessage(this.getBaseHeads("GET", StringUtils.isBlank(target.getFile())?"/":target.getFile(), null));
			receiveMessage();
		} catch (ProtocolException p) {
			logger.error("Http.get() ProtocolException.url:" + url, p);
			return;
		} catch (UnknownHostException e) {
			logger.error("Http.get() UnknownHostException.url:" + url, e);
			return;
		} catch (IOException i) {
			logger.error("Http.get() IOException.url:" + url, i);
			return;
		}
	}

	/*
	 * HEAD方法只请求URL的元信息，不包括URL本身。若怀疑本机和服务器上的 文件相同，用这个方法检查最快捷有效。
	 */
	public void head(String url) {
		try {
			checkHTTP(url);
			openServer(target.getHost(), target.getPort());
			sendMessage(this.getBaseHeads("HEAD", StringUtils.isBlank(target.getFile())?"/":target.getFile(), null));
			receiveMessage();
		} catch (ProtocolException p) {
			logger.error("Http.head() ProtocolException.url:" + url, p);
			return;
		} catch (UnknownHostException e) {
			logger.error("Http.head() UnknownHostException.url:" + url, e);
			return;
		} catch (IOException i) {
			logger.error("Http.head() IOException.url:" + url, i);
			return;
		}
	}

	/*
	 * POST方法是向服务器传送数据，以便服务器做出相应的处理。例如网页上常用的 提交表格。
	 */
	public void post(String url, String content) {
		try {
			checkHTTP(url);
			openServer(target.getHost(), target.getPort());
			sendMessage(this
					.getBaseHeads("POST", StringUtils.isBlank(target.getFile())?"/":target.getFile(), content));
			receiveMessage();
		} catch (ProtocolException p) {
			logger.error("Http.head() ProtocolException.url:" + url
					+ ",content:" + content, p);
			return;
		} catch (UnknownHostException e) {
			logger.error("Http.head() UnknownHostException.url:" + url
					+ ",content:" + content, e);
			return;
		} catch (IOException i) {
			logger.error("Http.head() IOException.url:" + url + ",content:"
					+ content, i);
			return;
		}
	}

	protected void checkHTTP(String url) throws ProtocolException {
		try {
			URL target = new URL(url);
			if (target == null
					|| !target.getProtocol().toUpperCase().equals("HTTP"))
				throw new ProtocolException("这不是HTTP协议");
			this.target = target;
		} catch (MalformedURLException m) {
			throw new ProtocolException("协议格式错误");
		}
	}

	/*
	 * 与Web服务器连接。若找不到Web服务器，InetAddress会引发UnknownHostException
	 * 异常。若Socket连接失败，会引发IOException异常。
	 */
	protected void openServer(String host, int port)
			throws UnknownHostException, IOException {
		header.clear();
		content = null;
		try {
			if (client != null)
				closeServer();
			
			SocketAddress address = new InetSocketAddress(host, port == -1 ? 80
					: port);
			client = SocketChannel.open(address);
			client.configureBlocking(false);

		} catch (UnknownHostException u) {
			throw u;
		} catch (IOException i) {
			throw i;
		}
	}

	/* 关闭与Web服务器的连接 */
	protected void closeServer() throws IOException {
		if (client == null)
			return;
		try {
			client.close();
			// receiver.close();
		} catch (IOException i) {
			throw i;
		}
		client = null;
		receiver = null;
	}

	protected String getURLFormat(URL target) {
		String spec = "http://" + target.getHost();
		if (target.getPort() != -1)
			spec += ":" + target.getPort();
		return spec += target.getFile();
	}

	/* 向Web服务器传送数据 */
	protected void sendMessage(String data) throws IOException {
		Selector sel = SelectorProvider.provider().openSelector();
		ByteBuffer buf = ByteBuffer.allocate(data.length());
		buf.put(data.getBytes());
		buf.flip();
		client.write(buf);
		buf.flip();
		client.register(sel, client.validOps());
		SelectionKey sk = null;
		SocketChannel next = null;
		while (sel.isOpen()) {
			try {
				sel.select();
			} catch (IOException e) {
				logger.error(
						"Http.sendMessage() nio Selector.select() IOException",
						e);
			}
			Iterator<SelectionKey> it = sel.selectedKeys().iterator();
			while (it.hasNext()) {
				sk = it.next();
				it.remove();
				next = (SocketChannel) sk.channel();
				buf.clear();
				try {
					// check whether finish
					if (next.read(buf) == -1) {
						sk.cancel();
						next.close();
						if (!it.hasNext()) {
							sel.close();
						}
					}
				} catch (IOException e) {
					logger.error("Http.sendMessage()  close io IOException", e);
				}
				buf.flip();
				if (buf.limit() == 0) {
					continue;
				}
				byte b[] = new byte[buf.limit()];
				buf.get(b);
				if (next == client) {
					receiver = b;
				}
				
			}
		}
		buf.clear();
		buf = null;
	}

	/* 接收来自Web服务器的数据 */
	protected void receiveMessage() throws IOException {
		if (receiver == null || receiver.length < 1) {
			return;
		}
		BufferedReader rdr = new BufferedReader(new StringReader(new String(
				receiver)));
		System.out.println(new String(receiver));
		try {
			// Get request URL.
			String line = rdr.readLine();
			String[] url = line.split(" ");
			if (url.length < 3) {
				return;
			}

			header.put("version", url[0]);
			header.put("code", url[1]);
			header.put("message", url[2]);
			// Read header
			while ((line = rdr.readLine()) != null && line.length() > 0) {
				String[] tokens = line.split(": ");
				if(tokens!=null && tokens.length==2){
					header.put(tokens[0], tokens[1]);
				}else{
					logger.error("client request discover invalid result:"+line);
				}
				
			}
			if(StringUtils.equals(url[1], "200")){
				String contentLength = header.get("Content-Length");
				int len = StringUtils.isNotBlank(contentLength)?Integer.parseInt(contentLength):0;
				if(len>0){
					char[] buf = new char[len];
					if (rdr.read(buf) == len) {
						line = String.copyValueOf(buf);
					}

					if (line != null) {
						content = line;
					}
				}
			}
			
		} catch (IOException ex) {
			throw ex;
		}

		closeServer();
	}

	public String getContent() {
		return content;
	}

	public String getHeaderKey(int i) {
		if (i >= header.size())
			return null;
		Set<String> enums = header.keySet();
		String headerKey = null;
		int j = 0;
		for (String key : enums) {
			if (j == i) {
				headerKey = key;
				break;
			}
			j++;
		}
		return headerKey;
	}

	public String getHeaderValue(int i) {
		if (i >= header.size())
			return null;
		return header.get(getHeaderKey(i));
	}

	public String getHeaderValue(String key) {
		return header.get(key);
	}
	public Map<String,String> getHeader() {
		return header;
	}
	
	protected String getBaseHeads(String way, String path, String conent) {
		StringBuffer requestHead = new StringBuffer(512);
		// web的请求登录路径：demo为项目名称，user/login.do为登录的action
		requestHead.append(way);
		requestHead.append(" ");
		requestHead.append(path);
		requestHead.append(" HTTP/1.1\r\n");
		
		requestHead.append("Host: ");
		requestHead.append(this.target.getHost());
		if(this.target.getPort()!=80){
			requestHead.append(":");
			requestHead.append(this.target.getPort());
		}
		requestHead.append("\r\n");
		
		requestHead.append("Connection: keep-alive\r\n");

		if (StringUtils.equals("POST", way)) {
			requestHead.append("Content-Length: ");
			requestHead.append(conent != null ? conent.length() : 0);
			requestHead.append("\r\n");
		}
		requestHead.append("Origin: chrome-extension://aejoelaoggembcahagimdiliamlcdmfm\r\n");
		requestHead
				.append("User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n");
		requestHead.append("Content-Type: text/plain; charset=utf-8\r\n");
		requestHead.append("Accept: */*\r\n");
		requestHead.append("Accept-Encoding: gzip,deflate,sdch\r\n");
		requestHead.append("Accept-Language: zh-CN,zh;q=0.8\r\n");
		requestHead.append("Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n");
		requestHead.append("Keep-Alive: 300\r\n");
		requestHead.append("Cache-Control: private\r\n\r\n");
		if (StringUtils.equals("POST", way)) {
			requestHead.append(conent);
		}
		
		
		return requestHead.toString();
	}

	public boolean isOK() {
		return StringUtils.equals(this.header.get("code"), "200");
	}

	public static void main(String[] args) {
		Http http = new Http();
		// http.GET("http://192.168.1.5 );
		// int i;
		// for (i=0; i<50000; i++) {
		// http.GET("http://www.baidu.com/");
//		long time  =System.currentTimeMillis();
		HttpClientUtils client =new HttpClientUtils();
		System.out.println(new Date());
		http.post("http://wapdev3.dev.qunar.com/sandglass_job/",
				"method=doConfirmJob&mark=tongChengOrderJob");
//		List<NameValuePair> list = new ArrayList<NameValuePair>();
//		list.add(new BasicNameValuePair("method", "doConfirmJob"));
//		list.add(new BasicNameValuePair("mark", "tongChengOrderJob"));
//		client.post("http://wapdev3.dev.qunar.com/sandglass_job/", list);
		System.out.println(new Date());
		
		
		// }
	}
}